#pragma once

struct FileInfo
{
	std::wstring  strFileName;	// Only filename, no path
	INT64         nFileSize;
	FILETIME      ftLastWrite;
	DWORD         dwAttributes;
#ifdef _DEBUG
	// Ensure that FileInfo cannot be copied and assigned by lvalue
	std::unique_ptr<int> pReserved;
#endif
};

using BufferPtr = std::shared_ptr<void>;

class ICfTask
{
public:
	virtual INT64 GetKey() const = 0;
	virtual void Cancel() = 0;
	virtual bool IsCanceled() const = 0;
};

class IDirVisitor : public ICfTask
{
public:
	// Callbacks are ordered and will not continue until the last call returns
	virtual void OnVisit(FileInfo fileInfo) = 0;
	virtual void OnError() = 0;
};

using IDirVisitorPtr = std::shared_ptr<IDirVisitor>;

class IFileReader : public ICfTask
{
public:
	// Callbacks are ordered and will not continue until the last call returns
	virtual void OnOpen(INT64 nFileSize, FILETIME ftLastWrite) = 0;
	virtual void OnRead(BufferPtr pBuffer, INT64 nOffset, size_t nLength) = 0;
	virtual void OnError(INT64 nOffset, INT64 nLength) = 0;
};

using IFileReaderPtr = std::shared_ptr<IFileReader>;

class IPlugin
{
public:
	virtual void SetServer(LPCWSTR lpServerInfo) = 0;
	// The following 2 functions are called in the thread pool
	virtual bool VisitDir(LPCWSTR lpRemotePath, IDirVisitorPtr pCallback) = 0;
	virtual bool ReadFile(LPCWSTR lpRemotePath, IFileReaderPtr pCallback, INT64 nOffset, INT64 nLength) = 0;
//	virtual bool WriteFile(LPCWSTR lpLocalPath, LPCWSTR lpRemotePath, std::function<void(INT64/*nTotal*/, INT64/*nCompleted*/)> fnCallback) = 0;
};

using IPluginPtr = std::shared_ptr<IPlugin>;
